package org.shj.book1.ioblock;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

//调整 blockingCoefficient，可找出较少的执行时间
public class ConcurrentCal extends AbstractCalTotal{

	public double computeNetAssetValue(final Map<String, Integer> stocks)
			throws ExecutionException, InterruptedException, IOException {
		int numberOfCores = Runtime.getRuntime().availableProcessors();
		double blockingCoefficient = 0.9;
		final int poolSize = (int)(numberOfCores / (1 - blockingCoefficient));
		
		System.out.println("Pool size is: " + poolSize);
		
		List<Callable<Double>> partitions = new ArrayList<>();
		for(final String ticker : stocks.keySet()){
			partitions.add(new Callable<Double>(){
				public Double call() throws Exception{
					return stocks.get(ticker) * YahooFinance.getPrice(ticker);
				}
			});
		}
		
		final ExecutorService executorPool = Executors.newFixedThreadPool(poolSize);
		final List<Future<Double>> valueOfStocks = executorPool.invokeAll(partitions, 100, TimeUnit.SECONDS);
		
		double netAssetValue = 0.0;
		
		//每次循环只能取到一个子任务的结果，且子任务的顺序与我们创建的顺序是一致的。
		for(final Future<Double> vas : valueOfStocks){
			netAssetValue += vas.get(); //vas.get() 如果此任务尚未完成，程序会等待
		}
		
		executorPool.shutdown();
		return netAssetValue;
		
	}
	

	public static void main(String[] args)throws ExecutionException, InterruptedException, IOException{
		new ConcurrentCal().timeAndComputeValue();
	}
}
